home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / tcl / tclmotif.1 / tclmotif / tm.1.2 / src / tmDrag.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-10  |  11.8 KB  |  473 lines

  1. /*
  2.  * TmDrag.c --
  3.  *    This module contains the main set of functions
  4.  *    for drag and drop
  5.  *
  6.  * Copyright 1993 Jan Newmarch, University of Canberra.
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The author
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16.  
  17. #include "tm.h"
  18. #include "tmFuncs.h"
  19. #include <Xm/Xm.h>
  20.  
  21. #ifndef MOTIF11
  22. #include <Xm/DragDrop.h>
  23. #include <Xm/AtomMgr.h>
  24.  
  25. /* I shouldn't have to do this, but I do... */
  26. #ifdef DD_NAMES_CHANGED
  27. extern XtResource DSResources[];
  28. extern Cardinal NumDSResources;
  29. #else
  30. extern XtResource _XmDSResources[];
  31. extern Cardinal _XmNumDSResources;
  32. #endif
  33.  
  34. Boolean Tm_SettingDropResources = False;
  35. Boolean Tm_SettingDropProc = False;
  36.  
  37. Tm_Widget *Tm_HackWidgetPtr; /* see gripe in next function */
  38. Tm_Widget *Tm_HackDragWidgetPtr;
  39.  
  40.         
  41. /*--------------------------------------------------------------
  42.  *
  43.  * Tm_DragContextCmd --
  44.  *
  45.  *    This procedure is invoked to process the Tcl command
  46.  *    that corresponds to a widget managed by this module.
  47.  *    See the user documentation for details on what it does.
  48.  *
  49.  * Results:
  50.  *    A standard Tcl result.
  51.  *
  52.  * Side effects:
  53.  *    See the user documentation.
  54.  *
  55.  *--------------------------------------------------------------
  56.  */
  57.  
  58. int
  59. Tm_DragContextCmd(clientData, interp, argc, argv)
  60.     ClientData clientData;    /* Information about button widget. */
  61.     Tcl_Interp *interp;        /* Current interpreter. */
  62.     int argc;            /* Number of arguments. */
  63.     char **argv;        /* Argument strings. */
  64. {
  65.     Tm_Widget *butPtr = (Tm_Widget *) clientData;
  66.     char c;
  67.     Arg args[TM_MAXARGS];
  68.     int num_args;
  69.  
  70.     if (argc < 2) {
  71.     sprintf(interp->result,
  72.         "wrong # args: should be \"%.50s option [arg arg ...]\"",
  73.         argv[0]);
  74.     return TCL_ERROR;
  75.     }
  76.     c = argv[1][0];
  77.  
  78.     if ((c == 'd') && (strcmp(argv[1], "dropTransferStart") == 0)) {
  79.     Widget dropTransfer;
  80.     WidgetClass class = xmDropTransferObjectClass;
  81.  
  82.         XtInitializeWidgetClass(class);
  83. /* now we hit a big hole. From here, control goes to Tm_DropTransferHandler.
  84.  * we get there with the DropTransfer widget as 1st arg. Alas, woe, etc,
  85.  * there is no userData field on this animal for us to pass in a new wPtr
  86.  * for it. That means we've lost access to the Tcl interpreter :-(((.
  87.  * Solutions: (a) build a hash table from Xt widget to Tm widget. Cleanest,
  88.  * generalises to Xt, etc. (b) wave a magic wand so that there *is* a
  89.  * userData field. (c) Set a global with butPtr in it. Guess which hack
  90.  * we choose...
  91.  */
  92.     Tm_HackWidgetPtr = butPtr;
  93.  
  94.     /* hmmm, looks like we need to set some resources *right now*.
  95.        Pity the doco doesn't tell me this...
  96.      */
  97.     Tm_SetValues(butPtr->pathName, interp, butPtr->widget, butPtr->widget,
  98.             class, argv+2, argc-2, args, &num_args);
  99.     dropTransfer = XmDropTransferStart(butPtr->widget, args, num_args);
  100.  
  101. /*
  102.     Tm_SetValues(butPtr->pathName, interp, dropTransfer, dropTransfer,
  103.             class, argv+2, argc-2, args, &num_args);
  104.     XtSetValues(dropTransfer, args, num_args);
  105. */
  106.     }
  107.     return TCL_OK;
  108. }
  109.  
  110. /*
  111.  *--------------------------------------------------------------
  112.  *
  113.  * Tm_DropTransferHandler --
  114.  *
  115.  *    handler for when a drop starts moving data
  116.  *
  117.  * Results:
  118.  *
  119.  * Side effects:
  120.  *
  121.  *--------------------------------------------------------------
  122.  */
  123.  
  124. /* ARGSUSED */
  125. void
  126. Tm_DropTransferHandler(w, closure, seltype, type, value, length, format)
  127.     Widget w;
  128.     XtPointer closure;
  129.     Atom *seltype;
  130.     Atom *type;
  131.     XtPointer value;
  132.     unsigned long *length;
  133.     int *format;
  134. {
  135.     Tcl_Interp *interp;
  136.     Widget droppedOnWidget = (Widget) closure;
  137.     Tm_Widget *wPtr = Tm_HackWidgetPtr;  /* this is the drag context widget */
  138.     Tm_TransferStruct call_data;
  139.     Atom COMPOUND_TEXT;
  140.     Atom TEXT;
  141.     Atom STRING;
  142.     char *command;
  143.     char *new_command;
  144.     char *msg;
  145.  
  146.  
  147.     COMPOUND_TEXT = XmInternAtom(XtDisplayOfObject(w),
  148.                 "COMPOUND_TEXT", False);
  149.     TEXT = XmInternAtom(XtDisplayOfObject(w),
  150.                 "TEXT", False);
  151.     STRING = XmInternAtom(XtDisplayOfObject(w),
  152.                 "STRING", False);
  153.  
  154.     command = wPtr->transferProc;
  155.     interp = wPtr->interp;
  156.  
  157.     msg = NULL;
  158.     if (*type == COMPOUND_TEXT) {
  159.     /* I know nothing about Compound Strings, so I'll cheat
  160.        by letting Motif do the work
  161.      */
  162.     XmString xmstr;
  163.  
  164.     xmstr = XmCvtCTToXmString(value);
  165.     XmStringGetLtoR(xmstr, XmFONTLIST_DEFAULT_TAG, &msg);
  166.     XmStringFree(xmstr);
  167.     } else
  168.     if (*type == TEXT || *type == STRING) {
  169.     /* are these null terminated? just in case... */
  170.     msg = XtMalloc(*length + 1);
  171.     strncpy(msg, value, *length);
  172.     msg[*length] = '\0';
  173.     }
  174.     call_data.value = msg;
  175.     call_data.closure = (char *) closure;
  176.  
  177.     new_command = Tm_ExpandPercents(wPtr->pathName, w, NULL, 
  178.                 &call_data, command);
  179.  
  180.     if (Tcl_GlobalEval(interp, new_command) != TCL_OK) {
  181.         msg = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
  182.         if (msg == NULL) {
  183.             msg = interp->result;
  184.         }
  185.         XtAppWarningMsg(XtWidgetToApplicationContext(w),
  186.                 "TclError", "TclError", "TclError", msg, NULL, 0);
  187.     }
  188.  
  189.     XtFree(new_command);
  190. }
  191.  
  192. /*
  193.  *--------------------------------------------------------------
  194.  *
  195.  * Tm_DropProcHandler --
  196.  *
  197.  *    handler for when a drop starts on a widget
  198.  *
  199.  * Results:
  200.  *
  201.  * Side effects:
  202.  *
  203.  *--------------------------------------------------------------
  204.  */
  205.  
  206. void
  207. Tm_DropProcHandler(w, client_data, call_data)
  208.     Widget w;
  209.     XtPointer client_data;
  210.     XtPointer call_data;
  211. {
  212.     XmDropProcCallback dropData;
  213.     Tm_Widget *wPtr;
  214.     Tm_Widget *dcPtr;
  215.     Tcl_Interp *interp;
  216.     char *dropProc;
  217.     Widget dragContext;
  218.     char *command;
  219.  
  220.  
  221.     XtVaGetValues(w, XmNuserData, &wPtr, NULL);
  222.     dropProc = wPtr->dropProc;
  223.     interp = wPtr->interp;
  224.  
  225.     dropData = (XmDropProcCallback) call_data;
  226.     dragContext = dropData->dragContext;
  227.  
  228.     /* this thing has no Tm name yet */
  229.     dcPtr = (Tm_Widget *) XtMalloc(sizeof(Tm_Widget));
  230.     dcPtr -> interp = wPtr -> interp;
  231.     dcPtr -> widget = dragContext;
  232.     dcPtr -> pathName = XtMalloc(strlen(wPtr->pathName) + 3);
  233.     strcpy(dcPtr -> pathName, wPtr -> pathName);
  234.     strcat(dcPtr -> pathName, "..");
  235.     dcPtr -> parent = NULL;
  236.     dcPtr -> dropProc = NULL;
  237.  
  238.     Tm_StoreWidgetInfo(dcPtr->pathName, dcPtr, dcPtr->interp);
  239.  
  240.     Tcl_CreateCommand (dcPtr->interp, dcPtr->pathName, Tm_DragContextCmd,
  241.                  (ClientData) dcPtr, (void (*) ()) NULL);
  242.  
  243.     /* this damn thing has no class pointer!!! */
  244.     command = Tm_ExpandPercents(dcPtr->pathName, dcPtr->widget, dropData->event,
  245.             call_data, dropProc);
  246.  
  247.     if (Tcl_GlobalEval(interp, command) != TCL_OK) {
  248.     char *msg;
  249.  
  250.         msg = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
  251.         if (msg == NULL) {
  252.             msg = interp->result;
  253.         }
  254.         XtAppWarningMsg(XtWidgetToApplicationContext(w),
  255.                 "TclError", "TclError", "TclError", msg, NULL, 0);
  256.     }
  257.  
  258.     XtFree(command);
  259. }
  260.  
  261. /*
  262.  *--------------------------------------------------------------
  263.  *
  264.  * Tm_DropSiteSetValues --
  265.  *
  266.  *    set resource values on a widget
  267.  *
  268.  * Results:
  269.  *
  270.  * Side effects:
  271.  *
  272.  *--------------------------------------------------------------
  273.  */
  274.  
  275. void
  276. Tm_DropSiteSetValues(pathName, interp, w, argv, argc, args, num_args)
  277.     char *pathName;
  278.     Tcl_Interp *interp;
  279.     Widget w;
  280.     char **argv;
  281.     int argc;
  282.     Arg args[];
  283.     int *num_args;
  284. {
  285. #ifdef DD_NAMES_CHANGED
  286.     int num_resources = NumDSResources;
  287. #else
  288.     int num_resources = _XmNumDSResources;
  289. #endif
  290.     int num_values = 0;
  291.     XrmValue from, converted;
  292.     XtArgVal new_value;
  293.     char *resource;
  294.     char *value;
  295.     Tm_ClientData *client_data;
  296.  
  297.     if (argc > TM_MAXARGS*2) {
  298.     return;
  299.     }
  300.  
  301.     /* hack - how else do I tell between Drop set and FileSelBox set? */
  302.     Tm_SettingDropResources = True;
  303.  
  304.     while (argc >= 2) {
  305.     if (argv[0][0] != '-') {
  306.         /* skip this one silently */
  307.         argc -= 2; argv += 2;
  308.         continue;
  309.     }
  310.     resource = argv[0]+1;
  311.         value = argv[1];
  312.  
  313.     if (strcmp(resource, "dropProc") == 0) {
  314.         /* hack - how else do I tell between drop and drag Proc? */
  315.         Tm_SettingDropProc = True;
  316.     }
  317.  
  318. #ifdef DD_NAMES_CHANGED
  319.         if (Tm_ConvertValueFromStringQuark(w, DSResources, num_resources,
  320. #else
  321.         if (Tm_ConvertValueFromStringQuark(w, _XmDSResources, num_resources,
  322. #endif
  323.         resource, value, &new_value)) {
  324.             XtSetArg(args[num_values], resource, new_value);
  325.         num_values++;
  326.     } else {
  327.         fprintf(stderr, "Conversion from String to %s failed\n",
  328.                 resource);
  329.     }
  330.  
  331.     Tm_SettingDropProc = False;
  332.  
  333.     argc -= 2;
  334.     argv += 2;
  335.     }
  336.  
  337.     Tm_SettingDropResources = False;
  338.  
  339.     *num_args = num_values;
  340.  
  341.     /* memory leak: should XtFree all new_values stored in args[] */
  342. }
  343.  
  344. /*
  345.  *--------------------------------------------------------------
  346.  *
  347.  * Tm_DropSiteGetValues --
  348.  *
  349.  *    unused
  350.  *    get the resource values out of a widget
  351.  *
  352.  * Results:
  353.  *
  354.  * Side effects:
  355.  *
  356.  *--------------------------------------------------------------
  357.  */
  358.  
  359. void
  360. Tm_DropSiteGetValues(pathName, interp, w, class, argv, argc)
  361.     char *pathName;
  362.     Tcl_Interp *interp;
  363.     Widget w;
  364.     WidgetClass class;
  365.     char **argv;
  366.     int argc;
  367. {
  368.     XtResourceList resources;
  369.     int num_resources;
  370.     int num_values = 0;
  371.     XrmValue from, converted;
  372.     char *new_value;
  373. #   define MAXARGS 100
  374.     char *resource;
  375.     Tm_ClientData *client_data;
  376.     Widget parent;
  377.  
  378.     if (argc > MAXARGS*2) {
  379.     return;
  380.     }
  381.  
  382.     parent = XtParent(w);
  383.     XtGetResourceList(class, &resources, &num_resources);
  384.  
  385.     while (argc >= 2) {
  386.     if (argv[0][0] != '-') {
  387.         fprintf(stderr, "Skipping argument %s\n", argv[0]);
  388.         argc -= 2; argv += 2;
  389.         continue;
  390.     }
  391.     resource = argv[0]+1;
  392.  
  393.         if (Tm_ConvertValueToString(w, resources, num_resources,
  394.         resource, &new_value)) {
  395.         /* store new_value in variable in argv[1] now */
  396. #        ifdef DEBUG
  397.         fprintf(stderr, "Got value: %s\n", (char *) new_value);
  398. #        endif
  399. /*
  400.         Tcl_SetVar(interp, argv[1], (char *) new_value, TCL_GLOBAL_ONLY);
  401. */
  402.         Tcl_SetVar(interp, argv[1], (char *) new_value, 0);
  403.     } else {
  404.         fprintf(stderr, "Conversion from %s to String failed\n",
  405.                     resource);
  406.     }
  407.     argc -= 2;
  408.     argv += 2;
  409.     }
  410. }
  411.  
  412. Boolean Tm_ConvertProcHandler(w, selection, target, type, value, length, format)
  413.     Widget w;
  414.     Atom *selection;
  415.     Atom *target;
  416.     Atom *type;
  417.     XtPointer *value;
  418.     unsigned long *length;
  419.     int *format;
  420. {
  421.     extern Tm_Widget *Tm_HackDragWidgetPtr;
  422.     Tm_Widget *wPtr = Tm_HackDragWidgetPtr;
  423.     char *convertProc = wPtr->convertProc;
  424.     Tcl_Interp *interp = wPtr->interp;
  425.     char *command;
  426.     char *msg, *msg_type, *msg_value;
  427.     XmString xmstr;
  428.  
  429.  
  430.     Tcl_SetVar(interp, TM_CONVERT_TYPE, "", TCL_GLOBAL_ONLY);
  431.     Tcl_SetVar(interp, TM_CONVERT_VALUE, "", TCL_GLOBAL_ONLY);
  432.  
  433.     command = Tm_ExpandPercents(wPtr->pathName,
  434.                 w,
  435.                 NULL, NULL,
  436.                 convertProc);
  437.     if (Tcl_GlobalEval(interp, command) != TCL_OK) {
  438.         msg = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
  439.         if (msg == NULL) {
  440.             msg = interp->result;
  441.         }
  442.         XtAppWarningMsg(XtWidgetToApplicationContext(w),
  443.                 "TclError", "TclError", "TclError", msg, NULL, 0);
  444.     XtFree(command);
  445.         return False;
  446.     }
  447.     XtFree(command);
  448.  
  449.     /* now set results back into convertProc args */
  450.     msg_type = Tcl_GetVar(interp, TM_CONVERT_TYPE, TCL_GLOBAL_ONLY);
  451.     msg_value = Tcl_GetVar(interp, TM_CONVERT_VALUE, TCL_GLOBAL_ONLY);
  452.  
  453.     if (strcmp(msg_type, "COMPOUND_TEXT") == 0) {
  454.     char *passtext, *ctext;
  455.  
  456.     xmstr = XmStringCreateLocalized(msg_value);
  457.     ctext = XmCvtXmStringToCT(xmstr);
  458.     passtext = XtMalloc(strlen(ctext) + 1);
  459.     memcpy(passtext, ctext, strlen(ctext) + 1);
  460.  
  461.     *type = XmInternAtom(XtDisplay(w), "COMPOUND_TEXT", False);
  462.     *value = (XtPointer) passtext;
  463.     *length = strlen(passtext);
  464.     *format = 8;
  465.     XmStringFree(xmstr);
  466.  
  467.         return True;
  468.     }
  469.     return False;
  470. }
  471.  
  472. #endif /* not MOTIF11 */
  473.